#pragma once
#include "PFObject.h"

/******************************************************************************/
/*                                                                            */
/*   PFProcess class for Penguin Framework 0.1 (first draft)                  */
/*                                                                            */
/*   Process class description.                                               */
/*   ----------------------------------------------------------------------   */
/*   Processes are a key component of the Penguin Framework as they provide   */
/*   a mechanism for repetitive functionality.                                */
/*   User implementations can derive from this class and override the         */
/*   respective methods to implement functionality like data processing and   */
/*   I/O functionality.                                                       */
/*   The default implementation will return PF_ERROR_NOT_IMPLEMENTED on       */
/*   each method called.                                                      */
/*                                                                            */
/*                                                                            */
/*   Process data memory                                                      */
/*   ----------------------------------------------------------------------   */
/*   The process data (PD) memory paradigm is at the core of the Penguin      */
/*   Framework. Based on existing industrial and PLC systems, other           */
/*   applications and remote I/O can write to a process' PD memory, the data  */
/*   gets used in the process logic, and returned into the process memory.    */
/*                                                                            */
/*   During the processing of data, the process memory itself will be         */
/*   unchanged for reading or writing apps. Writes will only be committed     */
/*   after the next processing cycle.                                         */
/*                                                                            */
/*   Processes cam implement security mechanisms in their process data write  */
/*   and read routines to protect certain areas against unauthorized reads    */
/*   or writes.                                                               */
/*                                                                            */
/******************************************************************************/

#define PF_CLASS_PROCESS                    0x4000

#define PF_ERROR_ADDRESS_OUT_OF_RANGE		0x0100
/* Address for read or write request is out of range of the Process Data space.*/

#define PF_ERROR_INVALID_BLOCK_SIZE		    0x0200
/* Size of the data attempted to read/write from PD is too big and exceeds memory bounds. */

#define PF_ERROR_PERMISSION_DENIED		    0x4000
/* Attempt to read or write a block which is protected by this process. */

#define PF_ERROR_NOT_INITIALIZED			0x2000
/* Class data space is not initialized for use yet. */

#define STATUS_READY						0x0000	/* Process is idle */
#define STATUS_BUSY							0x0001	/* Process is currently crunching data. */
#define STATUS_ASYNC						0x0002	/* Process is busy but expecting data. */
#define STATUS_STOP							0x0004	/* Process has been stopped gracefully. */
#define STATUS_HALT							0x0008	/* Process has been deliberately stopped with saved state. */

#define STATUS_INIT							0x1000	/* Process is setting up memory. */
#define STATUS_FAULT						0xFFFF	/* Process encountered a fault condition and stopped. */

class PFProcess :
	public PPObject
{
public:

	PFProcess(void);

	virtual int Create();
	/* Set up internal data organisation and memory structure. */

	virtual int _executeCycle();
	/**
     * Run a full execution cycle. Basic implementation is to inhibit memory write access,
     * call the Run() method and copy the processed data into a fresh snapshot of the
     * PD memory used for reading.
     *
     * This method is used mostly for internal execution flow and most implementations
     * would not need to override it for any reason.
     */
	
    virtual int Run();
	/* Cycle through a single set of data processing. */

	virtual int ReadMemory(unsigned int dwAddress, unsigned int iLength, void * pData);
	/** 
     * Raw block read from process data memory. Default implementation will check memory size and
     * execute a dumb read.    
     */

	virtual int WriteMemory(unsigned int dwAddress, unsigned int iLength, void * pData);
	/**
     * Raw block write into process data memory. Default implementation will check size and blissfully
     * write over any existing memory.
     */

	virtual int GetStatus() { return iStatus; }
	/* Query object for internal status or error information. */
	
	virtual int GetCycleCount() { return iCycleCount; }
	/* Return the amount of executed cycles for this process. */

	virtual ~PFProcess(void);

protected:

	unsigned long * pProcessDataWrite;
	unsigned long * pProcessDataRead;
	
	/* Used in the Run() method, which should manipulate this process data block. */
	unsigned long * pProcessData;
	
	unsigned long iMemorySize;
    unsigned long iCycleCount;
    
	unsigned int iStatus;
};
